/* Junit sample */
package com.zooltech.samples.unittest;

/**
 * This class parse the given string to a float number
 *
 */
public class NumberParser {

    /**
     * isPositive flag.
     */
    private boolean isPositive = true;
    /**
     * 基数.
     */
    private static final int BASE_NUMBER = 10;

    /**
     * Parses the given string to a float number.
     *
     * @param number
     *            the given string
     * @return the float number related with the string
     *
     * @throws IllegalArgumentException
     *             if the string is empty,null or can not parse to a float
     */
    public float parse(String number) {
    //TODO ����
        if (null == number) {
//        if (null == number || "".equals(number)) {
            throw new IllegalArgumentException(
                    "Number string should not be empty or null");
        }
        StringIterator stringIterator = new StringIterator(number);
        getSign(stringIterator);
        int integer = getInteger(stringIterator);
        float fraction = getFraction(stringIterator);
        float total = integer + fraction;
        return isPositive ? total : (-1) * total;
    }

    /**
     * Gets the sign from StringIterator. If there's a sign in the
     * StringIterator, the boolean isPositive will be marked.
     *
     * @param si
     *            the StringIterator
     */
    private void getSign(StringIterator si) {
        char sign = si.next();
        if (sign == '+') {
            isPositive = true;
        } else if (sign == '-') {
            isPositive = false;
        } else {
            isPositive = true;
            si.pushPack();
        }
    }

    /**
     * Gets the integral part from the StringIterator.
     *
     * @param si the StringIterator
     *
     * @return int the Integral value of the string
     */
    private int getInteger(StringIterator si) {
        int integer = 0;
        while (si.hasNext()) {
            char next = si.next();
            if (next == '.') {
                return integer;
            }
            integer *= BASE_NUMBER;
            integer += parseSingleNumber(next);
        }
        return integer;
    }

    /**
     * Gets the fraction part from the StringIterator.
     *
     * @param si
     *            the StringIterator
     *
     * @return float the fraction value of the string
     */
    private float getFraction(StringIterator si) {
        float fraction = 0;
        //FIXME ʹ�ó���
        int divider = 10;
        while (si.hasNext()) {
            char next = si.next();
            float digit = parseSingleNumber(next);
            fraction = fraction + digit / (divider);
            divider *= 10;
        }
        return fraction;
    }

    /**
     * Parses the char to a related int value
     *
     * @param number
     *            the given char
     *
     * @return the int value related to the char
     *
     * @throws IllegalArgumentException
     *             if the number can not be parsed to an int
     */
    private int parseSingleNumber(char number) {
        if (number <= '9' && number >= '0') {
            return number - '0';
        } else {
            throw new IllegalArgumentException("It's not a number");
        }

    }
}


/**
 * This class is provided as an iterator over a string.
 *
 * @author Qianjp
 *
 */
class StringIterator {
    /**
     * 元素.
     */
    private String element;

    /**
     * 索引.
     */
    private int index;

    /**
     * Constructor
     *
     * @param element
     *            the String this Iterator is over
     */
    public StringIterator(String element) {
        this.element = element;
        index = 0;
    }

    /**
     * Checks if there's char remaining in this iterator
     *
     * @return true if not in the end
     */
    public boolean hasNext() {
        if (index < element.length()) {
            return true;
        }
        return false;
    }

    /**
     * Gets next char
     *
     * @return char
     */
    public char next() {
        index++;
        return element.charAt(index - 1);
    }

    /**
     * Pushes back a char
     *
     */
    public void pushPack() {
        if (index > 0) {
            index--;
        }
    }
}
